const tenthPowerOf2 = 1024;

class Validator {

  constructor(verifyData) {
    // 保存校验规则
    this.cache = [];
    this.verifyData = verifyData;
  }

  add(ruleName, errorMsg, ...args) {
    // 把校验的步骤包装起来，并且放入cache
    this.cache.push(() => {
      return Validator.strategies[ruleName].apply(this, [this.verifyData, errorMsg, ...args]);
    });
  }
  start() {
    for (let index = 0; index < this.cache.length; index++) {
      const validatorFunc = this.cache[index];
      // 开始校验，并取得校验后的返回信息
      const msg = validatorFunc();
      // 如果有确切的返回值，说明校验没有通过
      if (msg) {
        return msg;
      }
    }
  }
}

// 策略对象
Validator.strategies = {
  // 是否限制单个上传
  isSingle: (verifyData, errorMsg) => {
    if (verifyData.isSingle && verifyData.fileList.length >= 1) {
      return errorMsg;
    }
  },
  // 限制最大上传数量
  maxNumber: (verifyData, errorMsg, number) => {
    if (verifyData.fileList.length >= number) {
      return errorMsg;
    }
  },
  // 是否为合法类型
  isLegalType: (verifyData, errorMsg) => {
    // 如果未开启自定义格式
    if (!verifyData.allowedUploadFileFormat) {
      return;
    }
    // 如果没有填写或者为*，校验结果为通过
    if (verifyData.accept.trim() === '' || verifyData.accept.trim() === '*') {
      return;
    }
    // 包含统配符的格式list
    const wildcardFormatList = [];
    // 文件后缀名
    const fileSuffix = verifyData.file.name.split('.').pop();
    // 支持的格式list
    const fileFormatList = verifyData.accept.split(',').map((item) => {
      const type = item.trim();
      if (item.includes('/*')) {
        wildcardFormatList.push(type.split('/*').shift() ?? '');
      }
      return type;
    });
    // 媒体类型合法
    const isLegalMIMEType = fileFormatList.includes(verifyData.file.type ?? '');
    // 后缀名合法
    const isLegalSuffixType = fileFormatList.includes(`.${fileSuffix}`);
    // 通配符合法
    const isLegalWildcardType = wildcardFormatList.includes(
      verifyData.file.type?.split('/').shift() ?? '',
    );
    if (isLegalMIMEType || isLegalSuffixType || isLegalWildcardType) {
      return;
    }
    return errorMsg;
  },
  // 限制文件大小
  maximumFileSize: (verifyData, errorMsg, size) => {
    if (verifyData.file.size && verifyData.file.size / tenthPowerOf2 / tenthPowerOf2 > size) {
      return errorMsg;
    }
  },
};

export default Validator;
